#!/usr/bin/env python
# coding=utf-8
import re
import os

from google.appengine.ext import db, webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp import util

from model.model import Member, PassbyItem, Location
from model import get_member_by_username, get_member_by_id
from api import WriteJson
from google.appengine.api.datastore_types import GeoPt
import time
import datetime
from api.oauthRequest import BaseSourceOauthRequest
import hashlib
from geo import geohash
from config import LOCATION_PRECISION, ONE_DAY
from google.appengine.api import datastore_errors, memcache
from language import set_location_success
from location import memb_loc_info

def get_neighbors(hash_location,percision):
    result = geohash.expand(hash_location)
    i = 6
    while i>percision:
        temp = result[:]
        for area in temp:
            neighbors = geohash.neighbors(area)
            for neighbor in neighbors:
                if result.count(neighbor) < 1:
                    result.append(neighbor)
        i-=1
    return result

class SignUp(BaseSourceOauthRequest):
    def get(self):
        self.response.out.write('this is apis singup')
        #TO-DO
        pass
    
    def post(self):
        username = self.request.get('username').strip()
        password = self.request.get('password')
        email = self.request.get('email')
        usernameError = 0
        passwordError = 0
        emailError = 0
        usernameErrorMessage = ['',
                                '您输入的用户名长度小于3个字符',
                                '您输入的用户名长度大于12个字符',
                                '您输入的用户名已存在',
                                '您输入的用户名格式非法，只能使用字母，数字与下划线']
        passwordErrorMessage = ['',
                                '您输入的密码长度小于6位数',
                                '您输入的密码长度大于12位']
        emailErrorMessage = ['',
                             'email不能为空',
                             '您输入的email长度大于32位',
                             '您输入的email已经存在',
                             '您输入的email格式不正确']
        if len(username)<3:
            usernameError = 1#用户名过短
        elif len(username)>12:
            usernameError = 2#用户名过长
        else:
            if (re.search('^[a-zA-Z0-9\_]+$', username)):
                q = db.GqlQuery('SELECT __key__ FROM Member WHERE username = :1', username)
                if (q.count() > 0):
                    usernameError = 3#用户名已存在
            else:
                usernameError = 4#用户名非法
        if len(password)<6:
            passwordError = 1#密码过短
        elif len(password)>12:
            passwordError = 2#密码过长
        if (len(email) == 0):
            emailError = 1#email不能为空
        else:
            if (len(email) > 32):
                emailError = 2#email过长
            else:
                p = re.compile(r"(?:^|\s)[-a-z0-9_.]+@(?:[-a-z0-9]+\.)+[a-z]{2,6}(?:\s|$)", re.IGNORECASE)
                if (p.search(email)):
                    q = db.GqlQuery('SELECT __key__ FROM Member WHERE email = :1', email)
                    if (q.count() > 0):
                        emailError = 3#email已经存在
                else:
                    emailError = 4#email格式不正确
        
        if (usernameError + passwordError + emailError)>0:
            templateData = {}
            templateData['username'] = username
            templateData['password'] = password
            templateData['email'] = email
            templateData['usernameError'] = usernameError
            templateData['passwordError'] = passwordError
            templateData['emailError'] = emailError
            templateData['usernameErrorMessage'] = usernameErrorMessage[usernameError]
            templateData['passwordErrorMessage'] = passwordErrorMessage[passwordError]
            templateData['emailErrorMessage'] = emailErrorMessage[emailError]
            WriteJson(self,templateData,'signupError.json')
        else:
            p_sha1 = hashlib.sha1(password).hexdigest()
            member = Member(username=username,password=p_sha1,email=email)
            member.put()
            location = Location(member_id=str(member.key().id()))
            if self.request.get('latitude') and self.request.get('longitude'):
                location.location = GeoPt(float(self.request.get('latitude')),float(self.request.get('longitude')))
            else:
                location.location = GeoPt(23,110)
            location.put()
            template_values = {}
            template_values['one'] = member
            path = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static','api','member.json')
            WriteJson(self, template_values, path)
    
    
class QueryUser(BaseSourceOauthRequest):
    one = None
    def postHandler(self,member):
        if self.request.get('username') and self.request.get('username')!="":
            username = self.request.get('username')
            one = get_member_by_username(username)
        elif self.request.get('uid') and self.request.get('uid')!="":
            uid = self.request.get('uid')
            one = get_member_by_id(int(uid))
            
        if one:
            items = db.GqlQuery('SELECT * FROM PassbyItem WHERE member = :1', one)
            item = None
            if items.count() > 1:
                item = items[0]
            template_values = {}
            template_values['item'] = item
            template_values['one'] = one
            path = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static','api','member.json')
            WriteJson(self, template_values, path)
        else:
            template_values = {}
            template_values['result'] = False
            template_values['message'] = "User Not Found!"
            path = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static','api','normalResult.json')
            WriteJson(self, template_values, path)
            
class QueryLocalUsers(BaseSourceOauthRequest):
    def postHandler(self,member):
        try:
            location = GeoPt(self.request.get("location"))
        except datastore_errors.BadValueError, err:
            WriteJson(self, {"result":False,"message":err.message}, "normalResult.json")
        percision = 6
        if self.request.get('percision'):
            percision = self.request.get('percision')
        if percision>6 or percision<0:
            percision = 6
        hash_location = geohash.encode(location.lat, location.lon, 12)
        hash_location = hash_location[0:percision]
        neighbors = get_neighbors(hash_location[0:LOCATION_PRECISION],percision)
        template = {}
        template["members"] = []
        neighbors.sort()
        loactions = db.GqlQuery('SELECT * FROM Location WHERE hash_location >= :1 AND hash_location <= :2',neighbors[0],neighbors[-1])
        for location in loactions:
            memb = {}
            memb['member'] = location.member
            memb['location'] = location.location
            memb['current_item'] = memcache.get("PassByItem::"+str(location.member.key().id))
            template["members"].append(memb)
        WriteJson(self, template, 'members.json')
        
class UpdateLocalUsers(BaseSourceOauthRequest):
    def postHandler(self,member):
        try:
            location = GeoPt(self.request.get("location"))
        except datastore_errors.BadValueError, err:
            WriteJson(self, {"result":False,"message":err.message}, "normalResult.json")
        percision = 6
        if self.request.get('percision'):
            percision = self.request.get('percision')
        if percision>6 or percision<0:
            percision = 6
        hash_location = geohash.encode(location.lat, location.lon, 12)
        hash_location = hash_location[0:percision]
        neighbors = get_neighbors(hash_location[0:LOCATION_PRECISION],percision)
        template = {}
        template["members"] = []
        neighbors.sort()
        loactions = db.GqlQuery('SELECT * FROM Location WHERE hash_location >= :1 AND hash_location <= :2',neighbors[0],neighbors[-1])
        for location in loactions:
            time = datetime.datetime.today() - location.update_time
            if  time.time() < ONE_DAY:
                memb = {}
                memb['member'] = location.member
                memb['location'] = location.location
                memb['current_item'] = memcache.get("PassByItem::"+location.member.key().id)
                template["members"].append(memb)
        WriteJson(self, template, 'members.json')
        
class UpdataLocation(BaseSourceOauthRequest):
    def postHandler(self,member):
        try:
            location = GeoPt(self.request.get("location"))
        except datastore_errors.BadValueError, err:
            WriteJson(self, {"result":False,"message":err.message}, "normalResult.json")
            return
        loc = db.GqlQuery("SELECT * FROM Location WHERE member = :1", member)[0]
        loc.location = location
        loc.put()
        template = {}
        template['message'] = set_location_success
        template['username'] = loc.member.username
        template['location'] = self.request.get("location")
        WriteJson(self, template, "updateLocation.json")
            
class ModifyUser(BaseSourceOauthRequest):
    def requesHandler(self):
        uid = self.request.get('uid')
        username = self.request.get('username')
        one = get_member_by_id(uid)
        if one == False:
            one = get_member_by_username(username)
        if one is not False:
            birthdayError = 0
            genderError = 0
            birthdayErrorMessages = ["","非法生日"]
            genderErrorMessages = ["","非法性别"]
            try:
                bthd = time.strptime(self.request.get('birthday'),"%Y-%m-%d")
            except:
                birthdayError += 1
            genderArr = ["male","female","unkown"]
            if genderArr.count(self.request.get('gender'))==0:
                genderError += 1
            if (birthdayError + genderError) == 0:
                one.birthday = datetime.date(bthd[0],bthd[1],bthd[2])
                one.gender = self.request.get('gender')
                one.mark = self.request.get('mark')
                one.city = self.request.get('city')
                one.adress = self.request.get('adress')
                one.latestLoginTime = datetime.datetime.today()
                template_values = {}
                template_values['one'] = one
                path = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static','api','member.json')
                out = template.render(path, template_values)
                self.response.headers['Content-type'] = 'application/json'
                self.response.out.write(out)
            else:
                template_values = {}
                template_values['birthdayError'] = birthdayError
                template_values['genderError'] = genderError
                template_values['birthdayErrorMessage'] = birthdayErrorMessages[birthdayError]
                template_values['genderErrorMessage'] = genderErrorMessages[genderError]
                WriteJson(self, template_values, "modifyUserError.json")
        else:
            self.respose.set_status(400,'user nont find')
        

def main():
    application = webapp.WSGIApplication([('/api/user/signup',SignUp),
                                          ('/api/user/queryuser',QueryUser),
                                          ('/api/user/modifyuser',ModifyUser),
                                          ('/api/user/querylocalusers',QueryLocalUsers),
                                          ('/api/user/updatelocalusers',UpdateLocalUsers),
                                          ('/api/user/updateuserlocation',UpdataLocation)
                                          ],
                                         debug=True)
    util.run_wsgi_app(application)
    
if __name__ == "__main__":
    main()